﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.model.trap;
using l1cs.server.server.types;
using l1cs.server.model.map;
using l1cs.server.serverpackets;
using l1cs.server.model.skill;
using System.Collections;

namespace l1cs.server.model.Instance
{
    public class L1TrapInstance : L1Object
    {
        private readonly L1Trap _trap;
        private readonly Point _baseLoc = new Point();
        private readonly Point _rndPt = new Point();
        private readonly int _span;
        private bool _isEnable = true;
        private readonly String _nameForView;

        private ArrayList _knownPlayers = ArrayList.Synchronized( new ArrayList());

        private Random _random = new Random();

        public L1TrapInstance( int id, L1Trap trap, L1Location loc, Point rndPt, int span )
        {
            setId( id );
            _trap = trap;
            getLocation().set( loc );
            _baseLoc.set( loc );
            _rndPt.set( rndPt );
            _span = span;
            _nameForView = "trap";

            resetLocation();
        }

        public L1TrapInstance( int id, L1Location loc )
        {
            setId( id );
            _trap = L1Trap.newNull();
            getLocation().set( loc );
            _span = 0;
            _nameForView = "trap base";
        }

        public void resetLocation()
        {
            if ( _rndPt.getX() == 0 && _rndPt.getY() == 0 )
            {
                return;
            }

            for ( int i = 0; i < 50; i++ )
            {
                int rndX = _random.Next( _rndPt.getX() + 1 )
                        * ( _random.Next( 2 ) == 1 ? 1 : -1 ); // 1/2の確率でマイナスにする
                int rndY = _random.Next( _rndPt.getY() + 1 )
                        * ( _random.Next( 2 ) == 1 ? 1 : -1 );

                rndX += _baseLoc.getX();
                rndY += _baseLoc.getY();

                L1Map map = getLocation().getMap();
                if ( map.isInMap( rndX, rndY ) && map.isPassable( rndX, rndY ) )
                {
                    getLocation().set( rndX, rndY );
                    break;
                }
            }
            // ループ内で位置が確定しない場合、前回と同じ位置になる。
        }

        public void enableTrap()
        {
            _isEnable = true;
        }

        public void disableTrap()
        {
            _isEnable = false;

            foreach ( L1PcInstance pc in _knownPlayers )
            {
                pc.removeKnownObject( this );
                pc.sendPackets( new S_RemoveObject( this ) );
            }
            _knownPlayers.Clear();
        }

        public bool isEnable()
        {
            return _isEnable;
        }

        public int getSpan()
        {
            return _span;
        }

        public void onTrod( L1PcInstance trodFrom )
        {
            _trap.onTrod( trodFrom, this );
        }

        public void onDetection( L1PcInstance caster )
        {
            _trap.onDetection( caster, this );
        }


        public override void onPerceive( L1PcInstance perceivedFrom )
        {
            if ( perceivedFrom.hasSkillEffect( L1SkillId.GMSTATUS_SHOWTRAPS ) )
            {
                perceivedFrom.addKnownObject( this );
                perceivedFrom.sendPackets( new S_Trap( this, _nameForView ) );
                _knownPlayers.Add( perceivedFrom );
            }
        }
    }
}
